package com.lyhlmj.oop_client.ClientOperation.ClientUtil;

import com.lyhlmj.oop_client.ClientOperation.NetOperation.NetConnection;
import com.lyhlmj.oop_client.ClientOperation.NetOperation.NetPacket;
import com.lyhlmj.oop_client.Threads.GetChatInfoTask;
import com.lyhlmj.oop_client.Threads.GetPlayStatusTask;
import org.json.JSONObject;

import javax.swing.*;

//Client: 按长连接方式来实现 一个与后台进行交互的工具类
public class Client {
    //创建全局唯一客户端实例（单例模式）
    public static Client client = new Client();

    private String server;
    private int port;

    private String username;  //每次请求都要携带，相当于用户token

    private String[] players;  //获取对局的两个玩家的用户名
    private String chatRoomId;  //每次请求都要携带，相当于用户token
    private Integer playId;  //用户参与对局的信息

    public GetPlayStatusTask getPlayStatusTask;  //对局中获取用户状态的线程
    public GetChatInfoTask getChatInfoTask;  //获取对局中用户聊天信息的线程

    private NetConnection connection = null; // 维持一个连接

    private Client() {
    }

    public void setServer(String server) {
        this.server = server;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void send(JSONObject request, Callback callback) {
//        创建工作线程，实现数据发送
        SendTask task = new SendTask(request, callback);
        task.start();
    }

    // 此方法可能在多个线程里调用，所以添加互斥机制
    public synchronized JSONObject send(JSONObject request) throws Exception {
        // 第一次调用时，连接到服务器
        if (connection == null) {
            connection = new NetConnection();
            connection.connect(server, port, 3000);
        }
        connection.send((short) 0, request.toString(2));

        // 接收应答
        NetPacket response = connection.receive();
        JSONObject jresp = null;
        if (response != null) {
            jresp = new JSONObject(response.toString("UTF-8"));
        }
        return jresp;
    }

    // 自定义接口, 用于在GUI线程里处理的回调
    public interface Callback {
        void onResult(int status, String reason, JSONObject data);
    }

    ///////////////////////////////////////
    private class SendTask extends Thread {
        private JSONObject request;
        private Callback callback;

        public SendTask(JSONObject request, Callback callback) {
            this.request = request;
            this.callback = callback;
        }

        public void run() {
            int status = -1;
            String reason = null;
            JSONObject data = null;

            try {
                JSONObject jsonResp = send(request);  //调用发送方法，获取响应数据
                status = jsonResp.getInt("status");
                reason = jsonResp.optString("reason", "");
                data = jsonResp.optJSONObject("data");

            } catch (Exception e) {
                connection.close();
                connection = null;

                status = -1;
                reason = e.getMessage();
                if (reason == null) reason = e.getClass().getName();
            }

            // 在GUI线程中处理
            processResult(status, reason, data);
        }

        private void processResult(int status, String reason, JSONObject data) {
            if (callback != null) {
                SwingUtilities.invokeLater(() -> {
                    callback.onResult(status, reason, data);
                });
            }
        }
    }


    //////////////////////////////////////////
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getChatRoomId() {
        return chatRoomId;
    }

    public void setChatRoomId(String chatRoomId) {
        this.chatRoomId = chatRoomId;
    }

    public String[] getPlayers() {
        return players;
    }

    public void setPlayers(String[] players) {
        this.players = players;
    }

    public Integer getPlayId() {
        return playId;
    }

    public void setPlayId(Integer playId) {
        this.playId = playId;
    }

    public NetConnection getConnection() {
        return connection;
    }
}
